﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.StaticFiles;
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Yz.Base;
using Yz.Base.Enums;
using Yz.Core.Tools;

namespace Yz.Mvc.Controllers
{
    [Authorize]
    public class BaseController : Controller
    {
        public IHostingEnvironment _env { get; set; }
        #region Excel导出
        /// <summary>
        /// Excel导出
        /// </summary>
        /// <param name="npoiExcel"></param>
        /// <param name="excelName"></param>
        protected FileResult ExportExcel(NPOIExcel npoiExcel)
        {
            MemoryStream stream = YzNPOI.ExportExcel(npoiExcel);
            var provider = new FileExtensionContentTypeProvider();
            string fileExt = "";
            if (npoiExcel.ExcelType == ExcelType.Xls)
            {
                fileExt = ExcelSuffix.Xls;
            }
            else if (npoiExcel.ExcelType == ExcelType.Xlsx)
            {
                fileExt = ExcelSuffix.Xlsx;
            }
            npoiExcel.ExcelName = npoiExcel.ExcelName.Substring(0, npoiExcel.ExcelName.LastIndexOf("."));
            npoiExcel.ExcelName += fileExt;
            npoiExcel.ExcelName = WebUtility.UrlEncode(npoiExcel.ExcelName);
            var contentType = provider.Mappings[fileExt];
            Response.Headers.Add("fileName", npoiExcel.ExcelName);
            Response.Headers.Add("Content-Disposition", "attachment; filename=" + npoiExcel.ExcelName);
            //支持跨域时可以通过axios等http库获取到在header中的数据
            //Response.Headers.Add("Access-Control-Expose-Headers", "fileName");
            return File(stream.ToArray(), contentType, npoiExcel.ExcelName);
        }
        #endregion

        #region 用户属性
        /// <summary>
        /// 用户Id
        /// </summary>
        protected int UserId => 0;
        /// <summary>
        /// 用户姓名
        /// </summary>
        protected string UserName => "";
        #endregion

        #region 文件上传
        /// <summary>
        /// 文件根路径
        /// </summary>
        protected string FileRootPath
        {
            get
            {
                var dtNow = DateTime.Now;
                return "/FilesTemp/u" + UserId + "/" + dtNow.ToString("yyyyMM") + dtNow.ToString("yyyyMMdd") + "/";
            }
        }
        /// <summary>
        /// 临时文件根路径
        /// </summary>
        protected string TempFileRootPath
        {
            get
            {
                var dtNow = DateTime.Now;
                return "/File" + DateTime.Now.Year + "/" + dtNow.ToString("yyyyMMdd") + "/u" + UserId + "/";
            }
        }
        /// <summary>
        /// 合并文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="guid"></param>
        /// <returns></returns>
        protected VmUpFile MergeFile(string fileName, string guid)
        {
            var flExtension = fileName.Substring(fileName.LastIndexOf('.')).ToLower();
            var upFile = new VmUpFile();
            string tempFileRootPath = TempFileRootPath;
            var fileRootPath = FileRootPath;
            var tempFilePath = _env.ContentRootPath + tempFileRootPath + guid.Replace("-", "") + "/";
            if (!Directory.Exists(tempFilePath))
            {
                upFile.suc = false;
                upFile.msg = "文件上传失败！";
                upFile.chunk = false;
                return upFile;
            }
            var newFileName = DateTime.Now.ToString("yyyyMMddHHmmssfff");
            if (!Directory.Exists(_env.ContentRootPath + fileRootPath))
            {
                Directory.CreateDirectory(_env.ContentRootPath + fileRootPath);
            }
            var targetPath = Path.Combine(_env.ContentRootPath + fileRootPath, newFileName + flExtension);///合并后的文件路径

            var dcInfo = new DirectoryInfo(tempFilePath);
            var files = dcInfo.GetFiles();
            MergeTempFile(targetPath, files);
            if (files.Length == 0)
            {
                upFile.suc = false;
                upFile.msg = "文件上传失败！";
                return upFile;
            }

            upFile.suc = true;
            upFile.msg = "上传成功";
            upFile.File = new FileUp()
            {
                Name = fileName,
                Path = fileRootPath + newFileName + flExtension,
                FileSuffix = flExtension,
                FileType = FileType.Vdo,
                ThPath = FileThPath.Vdo
            };
            return upFile;
        }

        /// <summary>
        /// 合并临时文件
        /// </summary>
        /// <param name="targetPath"></param>
        /// <param name="files"></param>
        private void MergeTempFile(string targetPath, FileInfo[] files)
        {
            foreach (var file in files.OrderBy(f => int.Parse(f.Name)))
            {
                using (var addFile = new FileStream(targetPath, FileMode.Append, FileAccess.Write))
                {
                    using (var AddWriter = new BinaryWriter(addFile))
                    {
                        //获得上传的分片数据流
                        using (Stream stream = file.Open(FileMode.Open))
                        {
                            using (var TempReader = new BinaryReader(stream))
                            {
                                //将上传的分片追加到临时文件末尾
                                AddWriter.Write(TempReader.ReadBytes((int)stream.Length));
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 保存大文件
        /// </summary>
        /// <param name="chunk"></param>
        /// <param name="guid"></param>
        /// <param name="file"></param>
        /// <returns></returns>
        protected VmUpFile SaveBigFile(int chunk, string guid, IFormFile file)
        {
            //当前分片在上传分片中的顺序（从0开始） 
            var upFile = new VmUpFile();
            string tempFileRootPath = TempFileRootPath;
            var localPath = _env.ContentRootPath + tempFileRootPath + guid.Replace("-", "") + "/";
            if (!Directory.Exists(localPath))
            {
                Directory.CreateDirectory(localPath);
            }
            var flExtension = file.FileName.Substring(file.FileName.LastIndexOf('.')).ToLower();

            if (!FileTypeList.VdoList.Contains(flExtension))
            {
                upFile.suc = false;
                upFile.msg = "只能上传Mp4、mov格式的文件！";
                return upFile;
            }
            using (var addFile = new FileStream(localPath + chunk, FileMode.Append, FileAccess.Write))
            {
                using (var AddWriter = new BinaryWriter(addFile))
                {
                    using (var stream = file.OpenReadStream())
                    {
                        using (var TempReader = new BinaryReader(stream))
                        {
                            //将上传的分片追加到临时文件末尾
                            AddWriter.Write(TempReader.ReadBytes((int)stream.Length));
                        }
                    }
                }
            }
            upFile.File = new FileUp()
            {
                FileSuffix = flExtension,
                FileType = FileType.Vdo,
                Name = file.FileName
            };
            upFile.msg = "分片上传中";
            upFile.suc = true;
            return upFile;
        }

        /// <summary>
        /// 保存文件
        /// </summary>
        /// <param name="ft"></param>
        /// <param name="file"></param>
        /// <returns></returns>
        protected async Task<VmUpFile> SaveFile(FileType ft, IFormFile file)
        {
            var upFile = new VmUpFile();
            //创建文件夹 
            string fileRootPath = FileRootPath;
            var localPath = _env.ContentRootPath + fileRootPath;
            if (!Directory.Exists(localPath))
            {
                Directory.CreateDirectory(localPath);
            }
            var flExtension = file.FileName.Substring(file.FileName.LastIndexOf('.')).ToLower();
            #region 文件格式判断

            if (ft == FileType.Pic) //图片，判断图片格式的有效性
            {
                if (!FileTypeList.ImgList.Contains(flExtension))
                {
                    upFile.suc = false;
                    upFile.msg = "只能上传jpg,jpeg,png,bmp,gif格式的图片！";
                    return upFile;
                }
            }
            else if (ft == FileType.Doc)
            {
                if (!FileTypeList.DocList.Contains(flExtension))
                {
                    upFile.suc = false;
                    upFile.msg = "只能上传pdf格式的文档！";
                    return upFile;
                }
            }
            else if (ft == FileType.Vdo)
            {
                if (!FileTypeList.VdoList.Contains(flExtension))
                {
                    upFile.suc = false;
                    upFile.msg = "只能上传mp4、mov格式的视频！";
                    return upFile;
                }
            }
            else
            {
                upFile.suc = false;
                upFile.msg = "只能上传文档、图片和视频文件！";
                return upFile;
            }

            #endregion 文件格式有效性判断

            //保存原文件
            var newFileName = DateTime.Now.ToString("yyyyMMddHHmmssfff");
            var filePath = string.Format("{0}{1}{2}", fileRootPath, newFileName, flExtension);
            var fileLocalPath = string.Format("{0}{1}{2}", localPath, newFileName, flExtension);

            var fileThPath = ""; //缩略图路径
            upFile.suc = true;

            #region 图片

            if (FileTypeList.ImgList.Contains(flExtension)) //保存缩略图
            {
                var newThumbnailFileName = newFileName + "_th";
                fileThPath = string.Format("{0}{1}{2}", fileRootPath, newThumbnailFileName, flExtension);
                // var thFileLocalPath = string.Format("{0}{1}{2}", localPath, newThumbnailFileName, flExtension);
                // ImageProcessor.SaveImage(file.InputStream, fileLocalPath, thFileLocalPath);
            }

            #endregion  

            else
            {
                using (var stream = new FileStream(fileLocalPath, FileMode.Create))
                {

                    await file.CopyToAsync(stream);
                }
                #region 文档

                if (FileTypeList.DocList.Contains(flExtension)) //文档
                {
                    fileThPath = FileThPath.PDF;
                }

                #endregion  

                #region 视频文件

                else if (FileTypeList.VdoList.Contains(flExtension))
                {
                    fileThPath = FileThPath.Vdo;
                }

                #endregion 视频文件

                else
                {
                    upFile.suc = false;
                    upFile.msg = "只能上传文档、图片和视频！";
                }
            }
            upFile.suc = true;
            upFile.msg = "上传成功";
            upFile.File = new FileUp()
            {
                Name = file.FileName,
                FileSuffix = flExtension,
                ThPath = fileThPath,
                FileType = ft,
                Path = filePath
            };
            return upFile;
        }

        /// <summary>
        /// 保存临时文件
        /// </summary>
        /// <param name="ft"></param>
        /// <param name="file"></param>
        /// <returns></returns>
        protected async Task<VmUpFile> SaveTempFile(FileType ft, IFormFile file)
        {
            var upFile = new VmUpFile();
            string tempFileRootPath = TempFileRootPath;
            var localPath = _env.ContentRootPath + tempFileRootPath;
            if (!Directory.Exists(localPath))
            {
                Directory.CreateDirectory(localPath);
            }
            var flExtension = file.FileName.Substring(file.FileName.LastIndexOf('.')).ToLower();

            #region 文件格式有效性判断

            if (ft == FileType.Pic) //图片，判断图片格式的有效性
            {
                if (!FileTypeList.ImgList.Contains(flExtension))
                {
                    upFile.suc = false;
                    upFile.msg = "只能上传jpg,jpeg,png,bmp,gif格式的图片！";
                    return upFile;
                }
            }
            else if (ft == FileType.Doc)
            {
                if (!FileTypeList.DocList.Contains(flExtension))
                {
                    upFile.suc = false;
                    upFile.msg = "只能上传pdf,doc,docx格式的文档！";
                    return upFile;
                }
            }
            else if (ft == FileType.Vdo)
            {
                upFile.suc = false;
                upFile.msg = "只能上传mp4,mov格式的视频！";
                return upFile;
            }
            else
            {
                upFile.suc = false;
                upFile.msg = "只能上传文档、图片和视频！";
                return upFile;
            }

            #endregion 文件格式有效性判断

            //保存原文件
            var newFileName = DateTime.Now.ToString("yyyyMMddHHmmssfff");
            var filePath = string.Format("{0}{1}{2}", tempFileRootPath, newFileName, flExtension);
            var fileLocalPath = string.Format("{0}{1}{2}", localPath, newFileName, flExtension);
            //保存原文件
            using (var stream = new FileStream(fileLocalPath, FileMode.Create))
            {

                await file.CopyToAsync(stream);
            }
            upFile.suc = true;
            upFile.msg = "上传成功";
            upFile.File = new FileUp()
            {
                Name = file.FileName,
                Path = filePath,
                FileSuffix = flExtension,
                FileType = ft
            };
            return upFile;
        }
        #endregion

    }
}